{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.svm import SVC\n",
    "from sklearn.datasets import load_breast_cancer\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "\n",
    "# 加载并划分数据\n",
    "cancer = load_breast_cancer()\n",
    "X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0)\n",
    "\n",
    "# 计算训练数据的最小值和最大值\n",
    "scaler = MinMaxScaler().fit(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "测试集分数:0.97\n"
     ]
    }
   ],
   "source": [
    "# 对训练数据做缩放\n",
    "X_train_scaled = scaler.transform(X_train)\n",
    "svm = SVC()\n",
    "# 在缩放后的训练数据上学习SVM\n",
    "svm.fit(X_train_scaled,y_train)\n",
    "# 对测试数据做缩放\n",
    "X_test_scaled = scaler.transform(X_test)\n",
    "print(\"测试集分数:{:.2f}\".format(svm.score(X_test_scaled,y_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.1.用预处理进行参数选择"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best cross-validation:0.9812311901504789\n",
      "Best set score:0.97\n",
      "Best parameters: {'C': 1, 'gamma': 1}\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "# 只是为了便于说明,不要再实践中使用这些代码\n",
    "param_grid = {\"C\":[0.001,0.01,0.1,1,10,100],'gamma':[0.001,0.01,0.1,1,10,100]}\n",
    "grid = GridSearchCV(SVC(),param_grid=param_grid,cv=5)\n",
    "grid.fit(X_train_scaled,y_train)\n",
    "print(\"Best cross-validation:{}\".format(grid.best_score_))\n",
    "print(\"Best set score:{:.2f}\".format(grid.score(X_test_scaled,y_test)))\n",
    "print(\"Best parameters:\",grid.best_params_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<P>这是我们利用缩放后的数据对SVC参数进行网格搜索。但是，上面的代码中只有一个不易察觉的陷阱。在缩放数据时，我们使用了<strong>训练集中的所有数据</strong>来找到训练模型的方法。然后,我们使用缩放后的训练数据做交叉网格搜索。对于交叉验证的每次划分,原始训练集的一部分被划分为训练部分,一部分被划分为测试部分，测试部分用于度量在训练部分上所训练的模型在新数据上的表现。但是,我们在缩放数据时已使用过测试部分中所包含的信息。请记住，交叉验证每次划分的测试部分都是训练集中的一部分,我们使用整个训练集的信息来找到数据的正确缩放</P>\n",
    "<P>对于模型来说,这些数据与新数据看起来截然不同。如果我们观察新数据(比如测试集中的数据),那么这些数据并没有用于对训练数据进行缩放，其最大值和最小值也可能与训练数据不同,下面这个列子显示了交叉验证与最终评估这两个过程中数据处理的不同之处</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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AAAREKYAAAAAIALCFAAAAABEQJgCAAAAgAgIUwAAAAAQAWEKAAAAACIgTAEAAABABIQpAAAAAIiAMAUAAAAAERCmAAAAACACwhQAAAAARECYAgAAAIAICFMAAAAAEAFhCgAAAAAiIEwBAAAAQASEKQAAAACIgDAFAAAAABEQpgAAAAAgAsIUAAAAAERAmAIAAACACAhTAAAAABABYQoAAAAAIiBMAQAAAEAEhCkAAAAAiIAwBQAAAAAREKYAAAAAIALCFAAAAABEQJgCAAAAgAgIUwAAAAAQAWEKAAAAACIgTAEAAABABIQpAAAAAIiAMAUAAAAAERCmAAAAACACwhQAAAAARECYAgAAAIAIUhM9AOBg0qJFi42FhYXtEz2OhiotLW3T7t27MxI9DiCZsZ0B20qg/pi7J3oMwEHDzJz/c9GZmdzdEj0OIJmxnQHbSqD+cJkfAAAAAERAmAIAAACACAhTAAAAABABYQoAAAAAIiBMAYiLHTt26MYbb1RWVpZSU1NlZlqxYoUWLVokM9P48eMTPUQAqDMFBQUyM40YMaLU9BEjRsjMVFBQkJBxAahbhCkgiRQVFWnKlCnKzs7W4YcfrqZNm6pdu3Y6+eSTNWrUKM2ZM0eStH//fh111FEyM61cubLKPnfv3q309HQ1a9ZMmzdvLjVv165deuSRR9SrVy+1a9dOzZo1U3p6us444wzdfvvtWrNmTY3HPmbMGD366KPq1q2bxo0bp9zcXGVkVP5k3pycHJnxsCmgvjXk7czBqLKQBiA58HemgCRRVFSk/v3769VXX1V6err69eunTp06aevWrVq9erWefPJJffjhhxowYICaNGmikSNHasKECZo6daoeeuihSvt99tlntX37dg0ZMkTt2rUrmb506VINGTJEGzZsUKdOndS3b19lZmZq165devfdd3XffffpgQce0NKlS9WzZ89qxz937lwdf/zxeumll0pNb926tVatWqW2bdtG/3AAxEVD3840RPfcc4/Gjh2rjh07JnooAOqCu9NotHpqwX+5ik2fPt0leffu3X3btm3l5u/atcsXLFhQ8nrdunWekpLibdu29T179lTa77nnnuuS/LXXXiuZtmrVKm/durU3adLE7733Xt+7d2+55dasWeNXXnmlL1y4sNK+Y5mZZ2dn16jW3T07O9ur+jwqEtYn/PtIoyVza8zbmWSWn5/vknz48OEJ75dtJY1Wfy3hA6DRDqZW1UHO6NGjXZI//PDDldaU1a9fP5fkTz/9dIXzV61a5ZK8S5cuvn///pLpvXv3dkk+bty4atdRWFhY5fziUFS2FQerhQsXuiTPzc11928ODKpapjIcINBo1bfGuJ1xd8/Ly3NJnpeX53PnzvWzzz7bW7Zs6enp6X7FFVf4Rx99VG6Z4cOHuyRfvXq1T5o0ybt16+ZpaWmltjVbtmzxsWPH+gknnOBpaWneunVr79Wrl8+fP7/CcezYscNvvvlm79ixozdv3ty7du3qDz74oK9evbrC0FM8hvz8/HJ9vf322z506FDPzMz0Zs2aeUZGhl900UX+zDPPuLt7bm5updvLvLy8Sj8rtpU0Wv01LvMDksQRRxwhSfroo49qvMx1112nl19+WVOnTtVVV11Vbv6UKVMkSaNGjSq5Pyk/P19vvPGG0tLSNGbMmGrX0bx58yrnjxgxQjk5OZowYYI6d+5ccl1/VlZWhfXp6enKzc3VtGnTtHbtWuXm5pbMq2wZAPHRULczsZ5//nm98sorGjx4sHJycrRixQrNmjVLCxcu1JIlS9S1a9dyy9x0001avHix+vXrp759+yolJUWStHbtWuXk5KigoEDnn3++LrnkEu3atUtz587VJZdcoscff1zXXXddST979uzRhRdeqHfeeUfdu3fXsGHDtG3bNt1111168803a/wepOBzGz16tFJSUjRgwAAdd9xx2rx5s5YtW6bJkydr6NChysnJ0bZt2zRx4kR1795dgwYNKlm+R48etVofgDqS6DRHox1MTVX8xnj58uXetGlTNzP/wQ9+4LNmzfKCgoJK693d9+3b55mZmW5mvmbNmlLz9uzZ40ceeaSnpqb6Z599VjL9iSeecEl+7rnnVtl3bamSM0tlz0wV4zI/Gq1uWmPdzhSfmZLkL730Uql5jzzyiEvyXr16lZpefFYoMzOz3Njdg+2QmflTTz1VavqXX37p3bt397S0NN+4cWPJ9Lvvvtsl+eWXX+5FRUUl09esWeOHHXZYjc9M/fOf//TU1FQ/7LDD/IMPPig3rk8++aTkay7zo9GSu/E0PyBJnHLKKZoxY4bat2+vGTNm6IorrlBWVpaOOOIIDR48uNyDHSQpJSVFI0eOlLvrD3/4Q6l5L7zwgj7//HNddtllpZ6q99lnn0mSOnXqVLdvCEDSaQzbmV69eql///6lpt1www065phjtGDBAq1du7bcMmPGjFGXLl1KTXvvvff05ptv6oorrtDVV19dal56eromTJigwsJCzZo1q2R6Xl6emjRpovvvv19NmnxzCNWlSxfdeOONNX4Pv/vd77Rv3z7deeedOumkk8rNZ/sMNByEKSCJDB06VOvWrdP8+fN15513qn///tq/f79eeOEFDRgwQMOHD5e7l1pm1KhRatKkifLy8lRUVFQyferUqZKkH//4x6Xqi5fnseTAwamhb2eys7PLTUtJSdF5550nSXr33XfLzT/jjDPKTXvrrbckSdu3b9f48ePLtddee02StGrVKknSV199pX//+9/q2LGjjjnmmHL95eTk1Pg9LF26VJJ06aWX1ngZAMmJe6aAJNO0aVNdfPHFuvjiiyUFjzKeNWuWRo4cqSeeeEKDBw8udd18586dddFFF2n+/PmaN2+eLrvsMhUUFOiNN95Q586dS/oplpmZKUlav359/b0pAEmlIW9n2rdvX+H04jNj27dvr3RerC1btkiSXn/9db3++uuVrm/nzp2l+q1u/TWxbds2SeJx6UAjwJkpIMmlpKRo6NChuvnmmyVJCxYsKFdT/Fvh4hvB//CHP8jd9aMf/ajUpSiSSn57u2zZsgoPOgAcfBrSdmbTpk0VTt+4caMkqU2bNuXmVXSGrLhu4sSJVd4PkZeXV6q+uvXXRHp6uiRpw4YNNV4GQHIiTAENRKtWrSSp3OU3kjRgwABlZGRo3rx5+uSTTzRt2rSS+xzK6tKli3r37q3CwkI98MAD1a53z549Bz74ChQ/TSv2kiEAidUQtjMVPTWvqKhIf/3rXyUF94XVxFlnnSVJWrx4cY3qW7VqpWOPPVYbNmzQ6tWry81ftGhRjfqJXfcrr7xSbS3bSiC5EaaAJPHUU0/p9ddf1/79+8vN27hxY8lvg7/73e+Wm5+amqoRI0aoqKhIw4YN0/r169W3b99KLyF59NFH1bp1a91zzz168MEHtW/fvnI169at09VXX11yX0G8FT+ied26dXXSP4DyGsN2ZsGCBZo7d26paY899phWr16tCy64QJ07d65RP6eddprOP/98Pf/88/rjH/9YYc3//u//avPmzSWvr732Wu3fv1+33nprqc8wPz9fkyZNqvF7GD16tFJTU3XXXXdp5cqV5ebHXh552GGHyczYVgJJinumgCTx9ttva+LEicrIyNB5551X8uSp/Px8vfzyy9q9e7cGDhyoIUOGVLj8ddddp/vuu6/kt6xlbwiPdcIJJ2j+/Pm64oor9Mtf/lITJ07UhRdeqMzMTO3atUvvvfee/va3v8nMdOutt8b/zUq68MILNXPmTF1++eXq27evWrRooc6dO+uHP/xhnawPQOPYzlx22WUaPHiwBg8erGOPPVbvvfee5s2bp8MPP1yTJ0+uxachPfnkk+rVq5d+9KMfadKkSTrzzDOVnp6u9evX6/3339cHH3ygt956S+3atZMk3XLLLXrhhRc0a9Ys9ezZU3369NH27dv1zDPP6Lvf/a7mzJlTo/WeeOKJmjx5sq6//nqdcsopGjhwoI477jht2bJFy5YtU6tWrbRw4UJJ0qGHHqozzzxTixcv1rBhw3T88ceX/G2qk08+uVbvF0AdSPSz2Wm0g6mpir//sm7dOn/sscd80KBBfvzxx3urVq28adOmnpGR4ZdeeqlPnz691N81qUjv3r1dknfq1Mn37dtXZa27+1dffeUPPfSQ5+TklPytmNatW3vPnj197NixFf5dlsqoln9nat++fT5u3Djv0qWLp6amVrp82XV4EnwfabRkbo11O1P8d6by8vL8pZde8rPOOstbtmzpbdq08csvv9z/9a9/lVumor/xVNaOHTv87rvv9p49e/ohhxziaWlpnpWV5X379vXHH3/cd+7cWap++/btfvPNN3tmZqY3b97cu3bt6r/5zW989erVNf47U8WWLFnil19+uR955JHetGlT79Chg/fp08dnzpxZqu7jjz/2/v37++GHH+5mVvI5VIZtJY1Wf83cy18XDaBumJnzfy46M5O780x3oAqNdTszbdo0XXvttcrLy9OIESMSPZykxrYSqD/cMwUAAAAAERCmAAAAACACwhQAAAAARMA9U0A9aqz3MtQX7gMAqsd2BmwrgfrDmSkAAAAAiIAwBQAAAAAREKYAAAAAIALCFAAAAABEQJgCAAAAgAhSEz0A4GCSlpa2yczaJ3ocDVVaWtqmRI8BSHZsZ8C2Eqg/PBodgCTJzGZI2uLuNyV6LAAQhZmdIOkJSbe5+xuJHg+Axo/L/ADIzA6RNEzSqESPBQAOwIWSTpc0ONEDAXBwIEwBAAAAQASEKQAAAACIgDAFAAAAABEQpgAAAAAgAsIUAAAAAERAmAIAAACACAhTAAAAABABYQoAAAAAIiBMAQAAAEAEhCkAAAAAiIAwBQAAAAAREKYAAAAAIALCFAAAAABEQJgCAAAAgAgIUwAAAAAQAWEKAAAAACIgTAEAAABABIQpAAAAAIggNZ6dmVl3ST3j2SeAenFI+G9LM7s2oSMBENUSd/9XlAXNrKmkfpIOi++Q6l3x9utaM1uW0JEcuN2S5rr7zkQPBEDlzN3j01GwId4q6dC4dAgAAGpjnbt3jrKgmV0l6ek4jwcH7lfunpvoQQCoXDzPTDVTEKSKJE2PY78A6scISbskzUzwOADUTlNJwyS1PYA+ipf9l6S3DnhEiXO4pAGSFktaneCxHIhvSzpTB/Y9BVAP4nqZX2iPu3OZENDw8P8WaIDM7BAFYSoe/uLuP41TX4jIzH6qIEwBSHI8gAIAAAAAIohnmCoK25449gkAAKoWj/3vnjL/IrH4fgANRNwu83P3QjP7iaQd8eoTAABULU773+clZUnKi8ugcKD4fgANRNye5gcAAAAABxPumQIAAACACAhTAAAAABABYQoAAAAAIiBMAQAAAEAEhCkAAAAAiIAwBQAAAAAREKYAAAAAIALCFAAAAABEQJgCAAAAgAgIUwAAAAAQAWEKAAAAACIgTAEAAABABIQpAAAAAIiAMAUAAAAAERCmAAAAACACwhQAAAAARECYAgAAAIAICFMAAAAAEAFhCgAAAAAiIEwBAAAAQASEKQAAAACIIDXRAwDQsLVo0WJjYWFh+0SPA1JaWtqm3bt3ZyR6HAAAHCzM3RM9BgANmJk525HkYGZyd0v0OAAAOFhwmR8AAAAARECYAgAAAIAICFMAAAAAEAFhCgAAAAAiIEwBaPSmTZsmM9O0adMSOo5ly5bpoosuUtu2bWVm6tGjhyRpxIgRMjMVFBQkdHwAAKB2eDQ6ANSDHTt2qF+/fiosLNQPf/hDtW3bVhkZlT/FvKCgQF26dNHw4cMTHgIBAEDFCFMAUA/+/ve/a/Pmzbr77rt12223lZp3zz33aOzYserYsWOCRgcAAKIgTAFAPfj0008lSZmZmeXmdejQQR06dKjvIQEAgAPEPVMA6tScOXN04YUXqkOHDmrevLkyMzOVnZ2tyZMnl6vdunWrbr/9dn3nO99Ry5Yt1aZNG3Xv3l1jx47Vrl27Sur+8Y9/6KabblL37t11+OGHKy0tTccdd5xuueUWffnll7Ua3/r163XDDTfo6KOPVvPmzXXEEUdowIABeuedd8rVjh8/XmamRYsW6cknn9SZZ56pQw89VFlZWZX2X1BQIDPT8OHDJUnXXnutzKzUPVxl75kaP368unTpIkn605/+VFKfDPd9AQCAb3BmCkCd+e///m/95Cc/UUZGhi677DK1bdtWmzdv1vvvv6+8vDz9x3/8R0ltfn6+LrjgAq1du1annnqqRo8erf379+ujjz7Sww8/rOuvv16HHHKIJGnKlCmaPXu2srOz1bt3bxUVFWn58uV66KGH9Morr+jtt99Wq1atqh3f8uXLdfHFF2vr1q3q06ePLr/8cn3xxRd64YUXdN5552n27Nnq27dvueUefPBBvf7667rssst0wQUXaPv27ZWuIz09Xbm5uVqxYoVefPFFDRw4sOTBE8X/lpWTk6Nt27Zp4sSJ6t69uwYNGlQyr7JlAABAArg7jUajRW7BZqRiPXv29GbNmvmmTZvKzfv8889LvT7nnHNckv/617+usHb37t0lrwsKCnzfvn3l6qZOneqS/N577y01PS8vzyV5Xl5eybS9e/f6Mccc482bN/dFixaVqt+wYYNnZmZ6RkaGFxYWlkzPzc11Sd6yZUtfvnx5pe+7IhWNodjw4cNdkufn55dMy8/Pd0k+fPjwGq8j/F4k/GeCRqPRaLSDpXGZH4A6lZqaqqZNm5ab3rZt25Kv//GPf2jJkiXq0aOHbr311gpr09LSSl537txZKSkp5epGjhyp1q1ba/78+dWO6+WXX9bq1av1s5/9TNnZ2aXmZWZmasyYMdq4caP+8pe/lFv2xz/+sU455ZRq1wEAABo3LvMDUGeGDRumW265RSeddJKuuuoqZWdn69xzz9WRRx5Zqm7p0qWSpD59+qhJk+p/x7N37149/vjjevrpp7Vy5Upt375d+/fvL5m/YcOGavt46623JElr167V+PHjy83/+OOPJUmrVq0qd6nfGWecUW3/AACg8SNMAagzv/jFL9S2bVtNnjxZkyZN0iOPPCIzU3Z2th544AGddtppkqRt27ZJUo0fDX7VVVdp9uzZOvroozVw4EBlZGSoefPmkqRHHnlEe/bsqbaPLVu2SJJmzpxZZd3OnTvLTavq70MBAICDB2EKQJ26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GDBATZo00ciRIzVhwgRNnTpVDz30UKX9Pvvss9q+fbuGDBmidu3alUxfunSphgwZog0bNqhTp07q27evMjMztWvXLr377ru677779MADD2jp0qXq2bNnteOfO3eujj/+eL300kulprdu3VqrVq1S27Zto384AHAQauj7hYbonnvu0dixY9WxY8dED6XhcXcajUar0xZsaio2ffp0l+Tdu3f3bdu2lZu/a9cuX7BgQcnrdevWeUpKirdt29b37NlTab/nnnuuS/LXXnutZNqqVau8devW3qRJE7/33nt979695ZZbs2aNX3nllb5w4cJK+45lZp6dnV2jWnf37Oxsr+rzqEhYn/DvI41Go8WrNeb9QjLLz893ST58+PCE99tY9m0JHwCNRmv8raqd5ujRo12SP/zww5XWlNWvXz+X5E8//XSF81etWuWSvEuXLr5///6S6b1793ZJPm7cuGrXUVhYWOX84lBUthUHq4ULF7okz83NdfdvdjRVLVOZxrLDodFotOLWGPcL7u55eXkuyfPy8nzu3Ll+9tlne8uWLT09Pd2vuOIK/+ijj8otM3z4cJfkq1ev9kmTJnm3bt08LS2t1L5hy5YtPnbsWD/hhBM8LS3NW7du7b169fL58+dXOI4dO3b4zTff7B07dvTmzZt7165d/cEHH/TVq1dXGHqKx5Cfn1+ur7ffftuHDh3qmZmZ3qxZM8/IyPCLLrrIn3nmGXd3z83NrXT/lpeXV+ln1Vj2bVzmByChjjjiCEnSRx99VONlrrvuOr388suaOnWqrrrqqnLzp0yZIkkaNWpUyf1J+fn5euONN5SWlqYxY8ZUu47mzZtXOX/EiBHKycnRhAkT1Llz55LrxLOysiqsT09PV25urqZNm6a1a9cqNze3ZF5lywDAwaih7hdiPf/883rllVc0ePBg5eTkaMWKFZo1a5YWLlyoJUuWqGvXruWWuemmm7R48WL169dPffv2VUpKiiRp7dq1ysnJUUFBgc4//3xdcskl2rVrl+bOnatLLrlEjz/+uK677rqSfvbs2aMLL7xQ77zzjrp3765hw4Zp27Ztuuuuu/Tmm2/W+D1Iwec2evRopaSkaMCAATruuOO0efNmLVu2TJMnT9bQoUOVk5Ojbdu2aeLEierevbsGDRpUsnyPHj1qtb4GKdFp7v+3d+fxUdX3/sffH0ggbALKEoJXEnErtrIpWKASEKUiO263qCxal9bWIl6xVq+xvVbFpUAp1roElUr9cVlEBRFFemlBBaNQC60IBARZFGSzhJLk+/vjnMRJJsvkZCYzSV7Px+M8YM55n/P9TjI53/OZOecMExNT3Z9UwTuQOTk5Ljk52ZmZu/baa938+fNdbm5uuXnnnMvPz3dpaWnOzNzWrVtLLDt+/Lhr27atS0pKcrt37y6e/8ILLzhJrm/fvhVuu6pUzidLpT+ZKsJpfkxMTEx1d1wo+mRKknv11VdLLJs2bZqT5AYOHFhiftGnQmlpaWF9d84bN8zMzZ07t8T8r776ynXt2tWlpKS4PXv2FM9/8MEHnSQ3evRoV1BQUDx/69atrnXr1hF/MvX3v//dJSUludatW7uPP/44rF+fffZZ8f/r82l+3M0PQFx1795dc+bMUfv27TVnzhyNGTNG6enpOuWUUzRq1KiwGztIUsOGDTVx4kQ55/Tss8+WWLZo0SJ98cUXGjZsWIm76u3evVuSdOqpp8b2CQEAqqUujAsDBw7U0KFDS8y77bbb1LlzZ61YsULbt28PW+euu+5SRkZGiXnr16/Xn//8Z40ZM0bXXHNNiWWtWrXSAw88oLy8PM2fP794fnZ2tho0aKCpU6eqQYNvDvUzMjL005/+NOLn8OSTTyo/P1/33Xefzj333LDljKceiikAcXfVVVdpx44dWrZsme677z4NHTpUhYWFWrRokYYPH65x48YVvZNZ7MYbb1SDBg2UnZ2tgoKC4vnPPPOMJOmmm24qkS9an9uSA0Diq+3jQv/+/cPmNWzYUP369ZMkffjhh2HLe/XqFTZvzZo1kqRDhw4pKysrbHrzzTclSZs2bZIkHTlyRJ9++qk6duyozp07h20vMzMz4ufw7rvvSpIuu+yyiNepj7hmCkBCSE5O1qWXXqpLL71Ukndr3Pnz52vixIl64YUXNGrUqBLnYXfq1EmXXHKJli1bpiVLlmjYsGHKzc3VW2+9pU6dOhVvp0haWpokaefOnTX3pAAAgdXmcaF9+/Zlzi/6ZOzQoUPlLgu1f/9+SdLy5cu1fPnycts7evRoie1W1n4kDh48KEncLr0SfDIFICE1bNhQV111lSZNmiRJWrFiRVim6F3GoguLn332WTnndMMNN5Q4tUFS8buB69atK3MQAwAktto0Luzdu7fM+Xv27JEktWzZMmxZWZ+QFeWmT59e4XU72dnZJfKVtR+JVq1aSZJ27doV8Tr1EcUUgITWokULSQo7nUOShg8frtTUVC1ZskSfffaZZs+eXXzefGkZGRkaNGiQ8vLy9Oijj1ba7vHjx6vf+TIU3Z0p9BQUAEDkasO4UNZd8woKCvSXv/xFknddWCQuvPBCSdKqVasiyrdo0UJnnHGGdu3apS1btoQtX7lyZUTbCW176dKllWbr89hGMQUgrubOnavly5ersLAwbNmePXuK31286KKLwpYnJSVp/PjxKigo0NixY7Vz504NGTKk3FMSfvvb3+qkk07SQw89pMcff1z5+flhmR07duiaa64pPk892opu+btjx46YbB8Aaru6MC6sWLFCr732Wol5M2fO1JYtWzRgwAB16tQpou2cf/75+t73vqcFCxboueeeKzPzt7/9Tfv27St+PGHCBBUWVN7DVgAAHbdJREFUFmrKlCklfobbtm3TjBkzIn4Ot956q5KSkvSrX/1KGzduDFseenpk69atZWb1cmzjmikAcfXee+9p+vTpSk1NVb9+/YrvZLRt2za9/vrrOnbsmEaMGKErrriizPV/+MMf6pFHHil+1670BcahzjnnHC1btkxjxozRnXfeqenTp+viiy9WWlqavv76a61fv15//etfZWaaMmVK9J+spIsvvljz5s3T6NGjNWTIEDVp0kSdOnXSddddF5P2AKC2qQvjwrBhwzRq1CiNGjVKZ5xxhtavX68lS5bo5JNP1qxZs6rw05BeeuklDRw4UDfccINmzJih3r17q1WrVtq5c6c2bNigjz/+WGvWrFG7du0kSZMnT9aiRYs0f/589ejRQ4MHD9ahQ4f08ssv66KLLtLixYsjardLly6aNWuWbrnlFnXv3l0jRozQmWeeqf3792vdunVq0aKF3nnnHUlS8+bN1bt3b61atUpjx47VWWedVfzdVOedd16Vnm+tE+97szMxMdX9SRV8n8iOHTvczJkz3ciRI91ZZ53lWrRo4ZKTk11qaqq77LLL3IsvvljiezLKUvQN9qeeeqrLz8+vMOucc0eOHHFPPPGEy8zMLP7ukZNOOsn16NHD3X333WV+z0d5VMXvmcrPz3c///nPXUZGhktKSip3/dJtuAT4PTIxMTFFa6qr40LR90xlZ2e7V1991V144YWuadOmrmXLlm706NHu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\n",
      "text/plain": [
       "<Figure size 1080x720 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import mglearn\n",
    "mglearn.plots.plot_improper_processing()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<P>因此,对于建模过程,交叉验证中的划分无法正确地反映新数据的特征。我们已经将这部分数据的信息泄露给建模过程。这将导致在交叉验证过程中获得过于乐观的结果,并可能导致选择次优的参数</P>\n",
    "<P>为了解决该问题,在交叉验证过程中,应该在进行预处理之前完成数据集的划分，任何从数据集中提取信息的处理过程都应该仅用于数据集的训练部分</P>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.2 构建管道\n",
    "<P>首先,我们需要构建一个有步骤列表组成的管道对象,每个步骤都是一个元组,其中包含一个名称(你选定的任意字符串)和一个估计器的实例:</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.pipeline import Pipeline\n",
    "# 我们创建了两个步骤,第一个叫做\"scaler\"的MinMaxScaler实例，第二个是叫做\"svm\"的SVC实例\n",
    "pipe = Pipeline([(\"scaler\",MinMaxScaler()),(\"svm\",SVC())])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pipeline(steps=[('scaler', MinMaxScaler()), ('svm', SVC())])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这里的pipe.fit()首先对一个步骤(scaler)调用fit，然后使用缩放器对训练数据做变换,最后用缩放后的数据拟合SVM\n",
    "pipe.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test score:0.97\n"
     ]
    }
   ],
   "source": [
    "# 要想在测试数据上做评估,我们只需调用pipe.score\n",
    "# 如果对管道调用score方法,则首先使用缩放器对测试数据进行变换，然后利用缩放后的数据对SVM调用score方法\n",
    "print(\"Test score:{:.2f}\".format(pipe.score(X_test,y_test)))\n",
    "# 利用管道,我们减少了\"预处理+分类\"的代码量,但是管道的主要优点在于,我们可以在\n",
    "# cross_val_score和GridSearchCV中使用这个估计器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.3 在网格搜索中使用管道"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<P>在网格搜索中使用管道的工作原理与使用任何估计器都相似,我们定义一个需要搜索的参数网格，并利用管道和参数网格构建一个GridSearchCV。不过在指定参数网格时有一处微小的变化。我们需要为每个参数指定它所属的步骤。我们要调节的两个参数C和gamma都是SVC的参数，属于第二个步骤(svm).为管道定义参数网络的语法是为每个参数指定步骤的名称，后面加上__(双下滑线),然后是参数名称。即分别以svm_C和svm_gamma作为参数网格的建</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "param_grid = {\"svm__C\":[0.001,0.01,0.1,1,10,100],\"svm__gamma\":[0.001,0.01,0.1,1,10,100]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best cross-validationcaccuracy:0.981\n",
      "Test set score:0.972\n",
      "best params:{'svm__C': 1, 'svm__gamma': 1}\n"
     ]
    }
   ],
   "source": [
    "grid = GridSearchCV(pipe,param_grid=param_grid,cv=5)\n",
    "grid.fit(X_train,y_train)\n",
    "print(\"Best cross-validationcaccuracy:{:.3f}\".format(grid.best_score_))\n",
    "print(\"Test set score:{:.3f}\".format(grid.score(X_test,y_test)))\n",
    "print(\"best params:{}\".format(grid.best_params_))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "与前面所作的交叉验证不同，现在对于交叉验证的每次划分来说,仅使用训练部分与MinMaxScaler拟合,测试部分的信息没有泄漏到参数搜索中，正如下图所示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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AIiAYgoAAAAAIqCYAgAAAIAIKKYAAAAAIAKKKQAAAACIgGIKAAAAACKgmAIAAACACCimAAAAACACiikAAAAAiIBiCgAAAAAioJgCAAAAgAgopgAAAAAgAoopAAAAAIiAYgoAAAAAIqCYAgAAAIAIKKYAAAAAIAKKKQAAAACIgGIKAAAAACKgmAIAAACACCimAAAAACCC1EQPAGgomjZtujU/P79tosdxpEtPT9+2f//+zESPAwAANHzm7okeA9AgmJnz/ynxzEzubokeBwAAaPg4zQ8AAAAAIqCYAgAAAIAIKKYAAAAAIAKKKQAAAACIgGIKOILMnDlTZqaZM2cmdBwrVqzQ5ZdfrtatW8vMdNZZZ0mSRo0aJTNTXl5eQscHAABQHdwaHUCd2r17t/r27av8/Hz98Ic/VOvWrZWZWfGdzPPy8tSpUyeNHDky4UUgAABALIopAHXqT3/6k7Zv36777rtPP/3pT0vMu//++zV+/Hi1a9cuQaMDAACoPoopAHXqyy+/lCRlZWWVmXf88cfr+OOPr+shAQAARMI1U0AdmTt3rnr27Knjjz9eTZo0UVZWlrp3767p06eXyX799de666679M///M9q1qyZWrZsqS5dumj8+PHat29fce7Pf/6zbr31VnXp0kXHHHOM0tPTddJJJ+n222/XN998U6Pxbdq0STfffLO+853vqEmTJjr22GM1YMAAffDBB2WykyZNkplpyZIleuGFF3T++efr6KOPVseOHSvsPy8vT2amkSNHSpKuv/56mVmJa7hKXzM1adIkderUSZL07LPPFueT4bovAAAAjkwBdeB//ud/9OMf/1iZmZnq37+/Wrdure3bt+vjjz9WTk6O/vVf/7U4m5ubq8suu0zr16/XOeeco7Fjx+rQoUP67LPP9Nhjj+mmm27SUUcdJUl66qmn9Nprr6l79+7q1auXCgsLtXLlSj366KN688039f7776t58+ZVjm/lypW64oor9PXXX6t3794aMmSI/v73v2vOnDnq1q2bXnvtNfXp06fMco888ogWLlyo/v3767LLLtOuXbsqXEdGRoYmTpyojz76SL/73e80cODA4htPFP1bWnZ2tnbu3KmpU6eqS5cuGjRoUPG8ipYBAACoM+5Oo9Hi0IL/TuXr2rWrN27c2Ldt21Zm3ldffVXi8UUXXeSS/Gc/+1m52f37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XbXHPm7cOD3++OM644wzNGHCBE2cOFGZmRXf6TU7O1tm9f7mRQBQq+rzfuFIVFGRdiTge6YAJFRhYaH69eunt956SxkZGerbt6/at2+vr7/+WmvXrtULL7ygTz/9VAMGDFCjRo00evRoTZ48WTNmzNCjjz5aYb+/+c1vtGvXLg0bNkxt2rQpnr58+XINGzZMmzdvVvv27dWnTx9lZWVp3759+vDDD/Xggw/q4Ycf1vLly9W1a9cqxz9v3jydfPLJev3110tMb9GihdasWaPWrVtHf3EA4AhU3/cL9dH999+v8ePHq127dokeSv3j7jQajVarLdjUlO/55593Sd6lSxffuXNnmfn79u3zRYsWFT/esGGDp6SkeOvWrf3AgQMV9nvxxRe7JH/77beLp61Zs8ZbtGjhjRo18gceeMAPHjxYZrl169b51Vdf7YsXL66w71hm5t27d69W1t29e/fuXtnrUZ4wn/DfI41Go8WrNeT9QjLLzc11ST5y5MiE99tQ9m0JHwCNRmv4rbKd5tixY12SP/bYYxVmSuvbt69L8pdeeqnc+WvWrHFJ3qlTJz906FDx9F69erkknzBhQpXryM/Pr3R+UVFUuhUVVosXL3ZJPnHiRHf/dkdT2TIVaSg7HBqNRitqDXG/4O6ek5PjkjwnJ8fnzZvnF154oTdr1swzMjJ86NCh/tlnn5VZZuTIkS7J165d69OmTfMzzjjD09PTS+wbduzY4ePHj/dTTz3V09PTvUWLFt6jRw9fsGBBuePYvXu333bbbd6uXTtv0qSJn3LKKf7II4/42rVryy16isaQm5tbpq/333/fhw8f7llZWd64cWPPzMz0yy+/3F9++WV3d584cWKF+7ecnJwKX6uGsm/jND8ACXXsscdKkj777LNqL3PjjTfqjTfe0IwZM3TNNdeUmf/UU09JksaMGVN8fVJubq7eeecdpaena9y4cVWuo0mTJpXOHzVqlLKzszV58mR16NCh+Dzxjh07lpvPyMjQxIkTNXPmTK1fv14TJ04snlfRMgBwJKqv+4VYr776qt58800NHjxY2dnZ+uijjzR79mwtXrxY7733nk455ZQyy9x6661aunSp+vbtqz59+iglJUWStH79emVnZysvL0+XXHKJrrzySu3bt0/z5s3TlVdeqSeffFI33nhjcT8HDhxQz5499cEHH6hLly4aMWKEdu7cqXvvvVfvvvtutZ+DFLxuY8eOVUpKigYMGKCTTjpJ27dv14oVKzR9+nQNHz5c2dnZ2rlzp6ZOnaouXbpo0KBBxcufddZZNVpfvZToao5GozX8pko+gVy5cqWnpaW5mfkPfvADnz17tufl5VWYd3cvKCjwrKwsNzNft25diXkHDhzw4447zlNTU33Lli3F05977jmX5BdffHGlfdeUKjiyVPrIVBFO86PRaLSGu18oOjIlyV9//fUS86ZMmeKSvEePHiWmFx0VysrKKjN292C/YWb+4osvlpj+zTffeJcuXTw9Pd23bt1aPP2+++5zST5kyBAvLCwsnr5u3Tpv1apVtY9M/fWvf/XU1FRv1aqVf/LJJ2XGtXHjxuKfj+TT/LibH4CEOvvsszVr1iy1bdtWs2bN0tChQ9WxY0cde+yxGjx4cJkbO0hSSkqKRo8eLXfX008/XWLenDlz9NVXX6l///4l7qq3ZcsWSVL79u1r9wkBAA5LQ9gv9OjRQ/369Ssx7eabb1bnzp21aNEirV+/vswy48aNU6dOnUpMW7Vqld59910NHTpU1157bYl5GRkZmjx5svLz8zV79uzi6Tk5OWrUqJEeeughNWr07Vv9Tp066ZZbbqn2c/jlL3+pgoIC3XPPPTr99NPLzGd/GqCYApBww4cP14YNG7RgwQLdc8896tevnw4dOqQ5c+ZowIABGjlyZNEnmcXGjBmjRo0aKScnR4WFhcXTZ8yYIUn60Y9+VCJftDy3JQeA5Fff9wvdu3cvMy0lJUXdunWTJH344Ydl5p933nllpi1btkyStGvXLk2aNKlMe/vttyVJa9askSTt2bNHX3zxhdq1a6fOnTuX6S87O7vaz2H58uWSpKuuuqrayxyJuGYKQFJIS0vTFVdcoSuuuEJScGvc2bNna/To0Xruuec0ePDgEudhd+jQQZdffrkWLFig+fPnq3///srLy9M777yjDh06FPdTJCsrS5K0adOmuntSAIDI6vN+oW3btuVOLzoytmvXrgrnxdqxY4ckaeHChVq4cGGF69u7d2+Jfqtaf3Xs3LlTkrhdehU4MgUgKaWkpGj48OG67bbbJEmLFi0qkyn6lLHowuKnn35a7q4bbrihxKkNkoo/DVyxYkW5OzEAQHKrT/uFbdu2lTt969atkqSWLVuWmVfeEbKi3NSpUyu9bicnJ6dEvqr1V0dGRoYkafPmzdVe5khEMQUgqTVv3lySypzOIUkDBgxQZmam5s+fr40bN2rmzJnF582X1qlTJ/Xq1Uv5+fl6+OGHq1zvgQMHDn/w5Si6O1PsKSgAgOqrD/uF8u6aV1hYqD/84Q+SguvCquOCCy6QJC1durRa+ebNm+vEE0/U5s2btXbt2jLzlyxZUq1+Ytf95ptvVpk9kvdtFFMAEurFF1/UwoULdejQoTLztm7dWvzp4qWXXlpmfmpqqkaNGqXCwkKNGDFCmzZtUp8+fSo8JeHxxx9XixYtdP/99+uRRx5RQUFBmcyGDRt07bXXFp+nHm9Ft/zdsGFDrfQPAPVdQ9gvLFq0SPPmzSsx7YknntDatWt12WWXqUOHDtXq59xzz9Ull1yiV199Vc8880y5mb/85S/avn178ePrr79ehw4d0p133lniNczNzdW0adOq/RzGjh2r1NRU3XvvvVq9enWZ+bGnR7Zq1UpmdkTu27hmCkBCvf/++5o6daoyMzPVrVu34jsZ5ebm6o033tD+/fs1cOBADRs2rNzlb7zxRj344IPFn9qVvsA41qmnnqoFCxZo6NChuuOOOzR16lT17NlTWVlZ2rdvn1atWqU//vGPMjPdeeed8X+yknr27KlXXnlFQ4YMUZ8+fdS0aVN16NBBP/zhD2tlfQBQ3zSE/UL//v01ePBgDR48WCeeeKJWrVql+fPn65hjjtH06dNr8GpIL7zwgnr06KEbbrhB06ZN0/nnn6+MjAxt2rRJH3/8sT755BMtW7ZMbdq0kSTdfvvtmjNnjmbPnq2uXbuqd+/e2rVrl15++WVdeumlmjt3brXWe9ppp2n69Om66aabdPbZZ2vgwIE66aSTtGPHDq1YsULNmzfX4sWLJUlHH320zj//fC1dulQjRozQySefXPzdVGeeeWaNnm+9k+h7s9NotIbfVMn3iWzYsMGfeOIJHzRokJ988snevHlzT0tL88zMTL/qqqv8+eefL/E9GeUp+gb79u3be0FBQaVZd/c9e/b4o48+6tnZ2cXfPdKiRQvv2rWrjx8/vtzv+aiIavg9UwUFBT5hwgTv1KmTp6amVrh86XV4EvweaTQaLV6toe4Xir5nKicnx19//XW/4IILvFmzZv+/vfuPj6K+8zj+/kBiFtCCNmISrQaoUrXKT6VFrgkVmx4oWHqevdLyw9pa++MsYpVa7kz7qFWoVcopV39cg6fV9jgJUEWo9codjwMFTdVrQUUhVFCCSgHBhPLje3/MJG42m+zuZHZ3SF7Px2MesDvv+X6/STbznc/uzMT17dvXTZ482b3yyitttkn2N54S7du3z916661u+PDhrk+fPi4Wi7ny8nI3fvx4d++997r9+/e3yu/du9fNnDnTlZWVuaKiIjd48GB3xx13uNdffz3tvzPVbO3atW7y5Mnu5JNPdoWFha60tNRVVVW5xYsXt8pt3rzZXXrppe6kk05yZtbyfWhPV5nbzPtaACB7zMyxrwnOzOSc457uALqMrjovLFq0SDNmzFBNTY2mT5+e7+FEWleZ27hmCgAAAAACoJgCAAAAgAAopgAAAAAgAK6ZApB1XfXc+FzpKueVA0Az5gV0lbmNT6YAAAAAIACKKQAAAAAIgGIKAAAAAAKgmAIAcgsOqwAAGltJREFUAACAACimAAAAACCAgnwPAEDXF4vFGszslHyP41gVi8Ua8j0GAAgT8wK6ytzGrdEBdGtmdpekYZIuds4dyfd4AABdm5ldLGmhpC8759bnezzoHE7zA9DdXSGpQlJpvgcCAOgWLpF0lqRP53sg6DyKKQAAAAAIgGIKAAAAAAKgmAIAAACAACimAAAAACAAiikAAAAACIBiCgAAAAACoJgCAAAAgAAopgAAAAAgAIopAAAAAAiAYgoAAAAAAqCYAgAAAIAAKKYAAAAAIACKKQAAAAAIgGIKAAAAAAKgmAIAAACAACimAAAAACAAiikAAAAACIBiCgAAAAACoJgCAAAAgADMORd+o2azJU0PvWEACN9g/98DkrbncyAAkIY6SVNcJw7gzOwCST+X1Ce0USETg+P+/0reRtG97ZM0wzn3p842lK1i6g1Jp4XeMAAAAE5zzu0IurGZ3SZpdojjAY5Fs51zczvbSEEYI0nC/H/HStqZpT4AIAwFkmKS9ud7IACQwn9L6q8PjrOCat7+Lkn3dbItBNNP0p58D6KbmiXpanX+90hS9oqpZq855zhtBgAAoJPM7FDITe5yzr0ccptApJnZu2G2xw0oAAAAACCAbH0ytVHScZJCrfwAAAC6sbCOrzb6/27qZDvAsSjU13+2bkBRICnmnOMaBAAAgBCEeXxlZv2cc1yzg24pzNd/VoopAAAAAOjquGYKAAAAAAKgmAIAAACAACimAAAAACAAiikAAAAACIBiCgAAAAACoJgCAAAAgAAopgAAAAAgAIopAAAAAAiAYgoAAAAAAqCYAgAAAIAAKKYAAAAAIACKKQAAAAAIgGIKAAAAAAKgmAIAAACAACimAAAAACAAiikAAAAACIBiCgAAAAACoJgCAAAAgAAopgAAAAAgAIopAAAAAAiAYgoAAAAAAijI9wAAHNt69eq1s6mp6ZR8jwNSLBZraGxsLMn3OAAA6C7MOZfvMQA4hpmZYz8SDWYm55zlexwAAHQXnOYHAAAAAAFQTAEAAABAABRTAAAAABAAxRQAAAAABEAxBaDLW7RokcxMixYtyus4nnvuOV1yySUqLi6WmWno0KGSpOnTp8vMVF9fn9fxAQCAzHBrdADIgX379mnChAlqamrSl7/8ZRUXF6ukpP27mNfX12vAgAGaNm1a3otAAACQHMUUAOTA+vXrtWvXLt166626+eabW6277bbbNHv2bJ166ql5Gh0AAAiCYgoAcuDNN9+UJJWVlbVZV1paqtLS0lwPCQAAdBLXTAHIquXLl+viiy9WaWmpioqKVFZWpoqKCi1cuLBNdvfu3fr+97+vj3/84+rdu7f69u2rIUOGaPbs2Tpw4EBL7vnnn9d1112nIUOG6KSTTlIsFtOZZ56pWbNm6S9/+UtG49u+fbu+9a1vaeDAgSoqKtKHP/xhTZw4URs2bGiTra6ulplp9erVeuSRRzRq1Cgdf/zxKi8vb7f9+vp6mZmmTZsmSZoxY4bMrNU1XInXTFVXV2vAgAGSpAcffLAlH4XrvgAAwAf4ZApA1tx333265pprVFJSossuu0zFxcXatWuXXnrpJdXU1Ogb3/hGS3br1q0aO3astm3bphEjRujaa6/V0aNH9eqrr+quu+7S17/+dfXp00eSdP/996u2tlYVFRUaN26cjhw5orq6Ot1555168skn9eyzz+qEE05IOb66ujp95jOf0e7du1VVVaXJkyfrnXfe0dKlSzVmzBjV1tZq/Pjxbbb76U9/qqeeekqXXXaZxo4dq71797bbR79+/XTLLbfohRde0LJlyzRp0qSWG080/5uosrJSe/bs0c9+9jMNGTJEl19+ecu69rYBAAB54JxjYWFhCbx4u5Hkhg8f7o477jjX0NDQZt3bb7/d6vHo0aOdJPfjH/84abaxsbHlcX19vTt8+HCb3AMPPOAkudtvv73V8zU1NU6Sq6mpaXnu0KFDbtCgQa6oqMitXr26VX7Hjh2urKzMlZSUuKamppbnb7nlFifJ9e7d29XV1bX7dSeTbAzNpk2b5iS5rVu3tjy3detWJ8lNmzYt7T78n0XeXxMsLCwsLCzdZeE0PwBZVVBQoMLCwjbPFxcXt/z/+eef19q1azV06FDddNNNSbOxWKzl8RlnnKGePXu2yV111VX60Ic+pFWrVqUc1xNPPKHXX39d3/72t1VRUdFqXVlZmW688Ubt3LlTTz/9dJttv/a1r2nYsGEp+wAAAF0bp/kByJopU6Zo1qxZOvfcc3XllVeqoqJCF110kU4++eRWuWeeeUaSVFVVpR49Ur/Hc+jQId1777361a9+pY0bN2rv3r06evRoy/odO3akbGPdunWSpG3btqm6urrN+s2bN0uSNm3a1OZUvwsvvDBl+wAAoOujmAKQNddff72Ki4u1cOFCLViwQPPnz5eZqaKiQj/5yU80cuRISdKePXskKe1bg1955ZWqra3VwIEDNWnSJJWUlKioqEiSNH/+fB08eDBlG++++64kafHixR3m9u/f3+a5jv4+FAAA6D4opgBk1dSpUzV16lTt2bNHa9euVW1trX7xi1+oqqpKmzZtUv/+/dWvXz9J6X2i9Nxzz6m2tlbjxo3TihUrWp1CePToUc2bNy+tcfXt21eStGzZMk2cODGjr8nMMsoDAICuiWumAOREv379NH78eN1///2aPn26du/erTVr1kiSPvGJT0iSVq1a1ep0vWRee+01SdLEiRPbXIu1fv16NTY2pjWe5j6bxxA1zdeEHTlyJM8jAQAA7aGYApA1K1eu1OHDh9s8v2vXLklS7969JUkjRozQ6NGj9cILL2ju3Llt8u+++66ampokqeVvOq1evbpNm9/85jfTHtukSZM0aNAg3XPPPVqxYkXSzLp16/T++++n3WaYTjzxRJmZ/vznP+elfwAAkBqn+QHImi984QuKxWIaM2aMysvL5ZzTmjVrtGHDBo0YMULjxo1ryT788MOqrKzUzTffrMcee0yVlZVyzmnz5s367W9/q5dfflnl5eW64IILdNFFF2nJkiUaPXq0xowZo4aGBj355JMaPHiwysrK0hpbYWGhlixZoqqqKk2YMEGjR4/W0KFD1bt3b73xxhvasGGDtmzZorfe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\n",
      "text/plain": [
       "<Figure size 1080x576 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import mglearn\n",
    "mglearn.plots.plot_proper_processing()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在交叉验证中,信息泄露的影响大小取决于预处理的步骤和性质.使用测试部分来估计数据的范围,通常不会产生可怕的影响，但在特征提取和特征选择中使用测试部分,则会导致结果的显著差异"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.4.通用的管道接口\n",
    "<P>Pipeline类不但可以用于预处理和分类,实际上还可以将任意数量的估计器连接在一起,例如你可以构建一个包含特征提取,特征选择,缩放和分类的管道.最后一步可以用聚类或回归替代</P>\n",
    "<P>对于管道中估计器的唯一要求就是,除了最后一步之外,其他所有步骤都需要具有transform方法，这样他们就可以生成新的数据表示,以供下一个步骤使用</P>\n",
    "<P>在调用pipeline.fit方法的过程中,管道内部依次对每个步骤fit和transform,其输入是前一个步骤transform方法的输出。对于管道中的最后一步,则仅仅调用fit</P>\n",
    "<P>请记住,pipeline是由元组组成的列表,所以pipeline.steps[0][1]是第一个估计器,pipeline.steps[1][1].是第二个。以此类推</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fit(self,X,y):\n",
    "    X_transformed = X\n",
    "    for name,estimator in selef.steps[:-1]:\n",
    "        # 遍历出最后一步之外的所有步骤\n",
    "        # 对数据进行拟合和变换\n",
    "        X_transformed = estimator.fit_transform(X_transformed,y)\n",
    "    # 对最后一步进行拟合\n",
    "    self.steps[-1][1].fit(X_transformed,y)\n",
    "    return self\n",
    "\n",
    "def predict(self,X):\n",
    "    X_trainsformed = X\n",
    "    for step in self.steps[:1]:\n",
    "        # 遍历除了最后一步之外的所有步骤\n",
    "        # 对数据做变换\n",
    "        X_transformed = step[1].transform(X_transformed)\n",
    "    # 利用最后一步做预测\n",
    "    sekf,steps[-1][1].predict(X_transformed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4.1 用make_pipeline方便的创建管道\n",
    "<p>make_pipeline方法可以为我们创建管道并根据每个步骤所属的类为其自动命名</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.pipeline import make_pipeline\n",
    "# 标准语法\n",
    "pipe_long = Pipeline([(\"scaler\",MinMaxScaler),(\"svm\",SVC(C=100))])\n",
    "#  缩写语法\n",
    "pipe_short = make_pipeline(MinMaxScaler(),SVC(C=100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pipeline steps:\n",
      "[('minmaxscaler', MinMaxScaler()), ('svc', SVC(C=100))]\n"
     ]
    }
   ],
   "source": [
    "# 通过steps属性查看pipe_short的命名\n",
    "# 一般来说步骤名称是类名称的小写版本，如果多个步骤是同一个类，则会附加一个数字\n",
    "print(\"Pipeline steps:\\n{}\".format(pipe_short.steps))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pipeline steps:\n",
      "[('standardscaler-1', StandardScaler()), ('pca', PCA(n_components=2)), ('standardscaler-2', StandardScaler())]\n"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.decomposition import PCA\n",
    "\n",
    "pipe = make_pipeline(StandardScaler(),PCA(n_components=2),StandardScaler())\n",
    "print(\"Pipeline steps:\\n{}\".format(pipe.steps))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4.2 访问步骤属性\n",
    "<p>通常来说,我们希望检查管道中每一步骤的属性--比如线性模型的系数或PCA提取的成分。可以通过named_steps属性访问,他是一个字典,将步骤名称映射为估计器</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "components.shape(2, 30)\n"
     ]
    }
   ],
   "source": [
    "# 用前面定义的管道对cancer数据集进行拟合\n",
    "pipe.fit(cancer.data,cancer.target)\n",
    "# 从pca步骤中提取前两个主成分\n",
    "components = pipe.named_steps['pca'].components_\n",
    "print(\"components.shape{}\".format(components.shape))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4.3 访问网格搜索管道中的属性\n",
    "<P>一个常见的任务是在网格搜索内访问管道的某些步骤</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best estimator:Pipeline(steps=[('standardscaler', StandardScaler()),\n",
      "                ('logisticregression', LogisticRegression(C=1, max_iter=200))])\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.datasets import load_breast_cancer\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.model_selection import train_test_split,GridSearchCV\n",
    "from sklearn.pipeline import make_pipeline\n",
    "\n",
    "cancer = load_breast_cancer()\n",
    "pipe = make_pipeline(StandardScaler(),LogisticRegression(max_iter=200))\n",
    "param_grid = {\"logisticregression__C\":[0.01,0.1,1,10,100]}\n",
    "X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=4)\n",
    "grid = GridSearchCV(pipe,param_grid,cv=5)\n",
    "grid.fit(X_train,y_train)\n",
    "\n",
    "# 从第5章可知,GridSearchCV找到的最佳模型保存在best_estimator_中\n",
    "print(\"Best estimator:{}\".format(grid.best_estimator_))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "logistic regression step:\n",
      ":LogisticRegression(C=1, max_iter=200)\n"
     ]
    }
   ],
   "source": [
    "print(\"logistic regression step:\\n:{}\".format(grid.best_estimator_.named_steps['logisticregression']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'GridSearchCV' object has no attribute 'best_estimator_'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-18-a4385b0f8070>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"逻辑回归的系数:\\n{}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgrid\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbest_estimator_\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnamed_steps\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'logisticregression'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcoef_\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'GridSearchCV' object has no attribute 'best_estimator_'"
     ]
    }
   ],
   "source": [
    "print(\"逻辑回归的系数:\\n{}\".format(grid.best_estimator_.named_steps['logisticregression'].coef_))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.5 网格搜索预处理与模型参数\n",
    "<P>在管道中,我们可以使用监督任务的输出来调节预处理参数.即我们可以在管道中同时搜索预处理参数和模型参数</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import load_boston\n",
    "from sklearn.linear_model import Ridge\n",
    "boston = load_boston()\n",
    "X_train,X_test,y_train,y_test = train_test_split(boston.data,boston.target,random_state=0)\n",
    "\n",
    "from sklearn.preprocessing import PolynomialFeatures\n",
    "pipe = make_pipeline(StandardScaler(),PolynomialFeatures(),Ridge())\n",
    "\n",
    "# 注意为__(双下滑线)\n",
    "param_grid = {\"polynomialfeatures__degree\":[1,2,3],'ridge__alpha':[0.001,0.01,0.1,1,10,100]}\n",
    "grid = GridSearchCV(pipe,param_grid=param_grid,cv=5,n_jobs=-1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GridSearchCV(cv=5,\n",
       "             estimator=Pipeline(steps=[('standardscaler', StandardScaler()),\n",
       "                                       ('polynomialfeatures',\n",
       "                                        PolynomialFeatures()),\n",
       "                                       ('ridge', Ridge())]),\n",
       "             n_jobs=-1,\n",
       "             param_grid={'polynomialfeatures__degree': [1, 2, 3],\n",
       "                         'ridge__alpha': [0.001, 0.01, 0.1, 1, 10, 100]})"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 7.21915761e-01,  7.21919281e-01,  7.21954085e-01,  7.22265610e-01,\n",
       "        7.23325945e-01,  7.07951636e-01,  7.60170834e-01,  7.59448408e-01,\n",
       "        7.66651449e-01,  7.94966818e-01,  8.28726141e-01,  8.04832665e-01,\n",
       "       -5.81095202e+02, -1.60898751e+02, -1.31972858e+01, -3.17933469e-02,\n",
       "        6.48340571e-01,  6.54083028e-01])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid.cv_results_['mean_test_score']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x222dc4a09a0>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.matshow(grid.cv_results_['mean_test_score'].reshape(3,-1),vmin=0,cmap='viridis')\n",
    "plt.xlabel(\"ridge__alpha\")\n",
    "plt.ylabel(\"polynomialfeatures_degree\")\n",
    "plt.xticks(range(len(param_grid['ridge__alpha'])),param_grid['ridge__alpha'])\n",
    "plt.yticks(range(len(param_grid['polynomialfeatures__degree'])),param_grid['polynomialfeatures__degree'])\n",
    "plt.colorbar()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 从图中可看出,使用二次多项式的效果最好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最好的参数组合:{'polynomialfeatures__degree': 2, 'ridge__alpha': 10}\n"
     ]
    }
   ],
   "source": [
    "print(\"最好的参数组合:{}\".format(grid.best_params_))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "验证集上最好的模型:Pipeline(steps=[('standardscaler', StandardScaler()),\n",
      "                ('polynomialfeatures', PolynomialFeatures()),\n",
      "                ('ridge', Ridge(alpha=10))])\n"
     ]
    }
   ],
   "source": [
    "print(\"验证集上最好的模型:{}\".format(grid.best_estimator_))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set score:0.77\n"
     ]
    }
   ],
   "source": [
    "# 这个最佳参数对应的分数\n",
    "print(\"Test set score:{:.2f}\".format(grid.score(X_test,y_test)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Score without poly features:0.63\n"
     ]
    }
   ],
   "source": [
    "# 为了对比,我们运行一个没有多项式特征的网格搜索\n",
    "param_grid = {\"ridge__alpha\":[0.001,0.01,0.1,1,10,100]}\n",
    "pipe = make_pipeline(StandardScaler(),Ridge())\n",
    "grid = GridSearchCV(pipe,param_grid=param_grid,cv=5)\n",
    "grid.fit(X_train,y_train)\n",
    "print(\"Score without poly features:{:.2f}\".format(grid.score(X_test,y_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.6网格搜索选择使用哪个模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "pipe = Pipeline([('preprocessing',StandardScaler()),('classifier',SVC())])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "param_grid = [\n",
    "    {'classifier':[SVC()],'preprocessing':[StandardScaler(),None],'classifier__gamma':[0.001,0.01,0.1,1,10,100],\n",
    "     'classifier__C':[0.001,0.01,0.1,1,10,100]},\n",
    "    {'classifier':[RandomForestClassifier(n_estimators=100)],'preprocessing':[None],'classifier__max_features':[1,2,3]}\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best params:\n",
      "{'classifier': SVC(C=10, gamma=0.01), 'classifier__C': 10, 'classifier__gamma': 0.01, 'preprocessing': StandardScaler()}\n",
      "Best cross-validation score:0.99\n",
      "Test-set score:0.98\n"
     ]
    }
   ],
   "source": [
    "X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0)\n",
    "grid = GridSearchCV(pipe,param_grid)\n",
    "grid.fit(X_train,y_train)\n",
    "print(\"Best params:\\n{}\".format(grid.best_params_))\n",
    "print(\"Best cross-validation score:{:.2f}\".format(grid.best_score_))\n",
    "print(\"Test-set score:{:.2f}\".format(grid.score(X_test,y_test)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.7 小结\n",
    "<P>本章中介绍了Pipeline类,这是一种通用工具,可以将机器学习工作流程中多个处理步骤链接在一起，形成一个单独的python对象</P>\n",
    "<P>我们可以在管道中使用网格交叉验证搜索,找到最佳参数组合与模型</P>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
